package com.sec.android.app.myfiles.widget.listview;

import android.content.Context;
import android.database.StaleDataException;
import android.os.Handler;
import android.util.SparseBooleanArray;
import android.view.View;
import android.view.ViewStub;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.Checkable;
import android.widget.ListView;

import com.sec.android.app.myfiles.decorator.AbsAdapterImpDecorator;
import com.sec.android.app.myfiles.decorator.dlpinfo.DlpAdapterDecorator;
import com.sec.android.app.myfiles.decorator.privateinfo.PrivateAdapterDecorator;
import com.sec.android.app.myfiles.feature.DlpMgr;
import com.sec.android.app.myfiles.feature.PrivateModeMgr;
import com.sec.android.app.myfiles.feature.ViEffectMgr;
import com.sec.android.app.myfiles.fragment.AbsMyFilesFragment;
import com.sec.android.app.myfiles.fragment.filelist.FileListAdapter;
import com.sec.android.app.myfiles.fragment.filelist.OnItemChangedListener;
import com.sec.android.app.myfiles.info.AppConstants.ViewType;
import com.sec.android.app.myfiles.info.AppFeatures;
import com.sec.android.app.myfiles.log.Log;
import com.sec.android.app.myfiles.module.abstraction.FileRecord;
import com.sec.android.app.myfiles.navigation.NavigationInfo;
import com.sec.android.app.myfiles.util.PreferenceUtils;
import com.sec.android.app.myfiles.widget.listview.listdecorator.AbsListDecorator;
import com.sec.android.app.myfiles.widget.listview.listdecorator.GridListPinchDecorator;

import java.lang.reflect.Method;
import java.util.ArrayList;

public abstract class AbsListViewImp {
    protected Context mContext;
    protected AbsListView mListView;
    protected FileListAdapter mAdapter;
    private boolean mSelectAll = false;
    private int mViewType = ViewType.LIST;
    protected AbsMyFilesFragment mFragment;
    protected NavigationInfo mNavigationInfo;

    private AbsListDecorator mDecorator;

    private ArrayList<OnItemChangedListener> mOnItemChangedListener = null;

    public static AbsListViewImp createListView(Context context, View view, NavigationInfo naviInfo) {
        int listType;
        FileRecord.StorageType storageType = naviInfo.getStorageType();
        switch (storageType) {
            case Search:
            case OptimizeStorage:
                listType = ViewType.LIST_DETAIL;
                break;
            case FolderTree:
                listType = ViewType.FOLDER_TREE;
                break;
            case Shortcut:
                listType = ViewType.LIST;
                break;
            case Blank:
                listType = ViewType.GRID;
                break;
            default:
                listType = PreferenceUtils.getViewAs(context, PreferenceUtils.getViewAsKey(naviInfo));
                break;
        }

        AbsListViewImp ret = null;
        switch (listType) {
            case ViewType.GRID:
                AbsListDecorator decorator = new GridListPinchDecorator();
                ret = new GridViewImp(context, view, decorator);
                decorator.setListInfo(context, ret, naviInfo);
                break;
            case ViewType.LIST:
            case ViewType.LIST_DETAIL:
                if (AppFeatures.isTabletUIMode()) {
                    if (storageType == FileRecord.StorageType.Downloads) {
                        ret = new DownloadColumnListViewImp(context, view, naviInfo);
                    } else if (storageType == FileRecord.StorageType.Search ||
                            naviInfo.isSelectOpDestination()) {
                        ret = new DetailListViewImp(context, view, naviInfo);
                    } else if (storageType == FileRecord.StorageType.OptimizeStorage) {
                        ret = new OptimizeStorageListViewImp(context, view, naviInfo);
                    } else if (storageType == FileRecord.StorageType.Shortcut) {
                        ret = new ShortcutListViewImp(context, view);
                    } else {
                        ret = new ColumnListViewImp(context, view, naviInfo);
                    }
                } else {
                    if (storageType == FileRecord.StorageType.OptimizeStorage) {
                        ret = new OptimizeStorageListViewImp(context, view, naviInfo);
                    } else if (storageType == FileRecord.StorageType.Shortcut) {
                        ret = new ShortcutListViewImp(context, view);
                    } else {
                        ret = new DetailListViewImp(context, view, naviInfo);
                    }
                }
                break;
            case ViewType.FOLDER_TREE:
                ret = new FolderTreeListViewImp(context, view);
                break;
            default:
                break;
        }

        if (ret != null && ret.mListView != null) {
            ret.setVisibility(View.VISIBLE);
            ret.mViewType = listType;
            ret.mFragment = naviInfo.getCurFragment();
        }

        return ret;
    }

    AbsListViewImp(Context context, View parentView) {
        _AbsListViewImp(context, parentView);
    }

    AbsListViewImp(Context context, View parentView, AbsListDecorator decorator) {
        mDecorator = decorator;
        _AbsListViewImp(context, parentView);
    }

    AbsListViewImp(Context context, View parentView, NavigationInfo navigationInfo) {
        mNavigationInfo = navigationInfo;
        _AbsListViewImp(context, parentView);
    }

    private void _AbsListViewImp(Context context, View parentView) {
        ViewStub stub = null;
        if (getViewStubId() >= 0) {
            stub = (ViewStub) parentView.findViewById(getViewStubId());
        }

        if (stub != null) {
            View view = stub.inflate();
            mListView = (AbsListView) view.findViewById(getListLayoutId());
        } else {
            mListView = (AbsListView) parentView.findViewById(getListLayoutId());
        }
        mContext = context;
    }

    public void setAdapter(FileListAdapter adapter) {
        mAdapter = adapter;
        mListView.setAdapter(adapter.getAdapter());

        if (DlpMgr.getInstance(mContext).dlpEnabled()) {
            AbsAdapterImpDecorator decorator = new DlpAdapterDecorator(mContext, mFragment, mAdapter);
            adapter.setDecorator(decorator);
        }
        if (PrivateModeMgr.getInstance(mContext).isReady()) {
            AbsAdapterImpDecorator decorator = new PrivateAdapterDecorator(mContext, mAdapter);
            adapter.setDecorator(decorator);
        }
    }

    public void addOnItemChangedListener(OnItemChangedListener listener) {
        if (mOnItemChangedListener == null) {
            mOnItemChangedListener = new ArrayList<>();
        }
        mOnItemChangedListener.add(listener);
    }

    public void removeOnCheckedItemChangedListener(OnItemChangedListener listener) {
        if (mOnItemChangedListener != null) {
            mOnItemChangedListener.remove(listener);
        }
    }

    public void notifyItemChecked() {
        if (mOnItemChangedListener != null) {
            for (OnItemChangedListener listener : mOnItemChangedListener) {
                if (listener != null) {
                    listener.onCheckedItemChanged();
                }
            }
        }
    }

    public FileListAdapter getAdapter() {
        return mAdapter;
    }

    public AbsMyFilesFragment getFragment() {
        return mFragment;
    }

    private void clearSelectedFile() {
        SparseBooleanArray arr = mListView.getCheckedItemPositions();
        if (arr != null) {
            int pos;
            for (int i = 0; i < arr.size(); i++) {
                if (arr.valueAt(i)) {
                    pos = arr.keyAt(i);
                    mListView.setItemChecked(pos, false);
                }
            }
        }
    }

    public void clearChoices() {
        mListView.clearChoices();
    }

    public void selectAll(boolean selectAll) {
        clearSelectedFile();
        mSelectAll = selectAll;
        mAdapter.selectAll(mSelectAll);
        notifyItemChecked();
    }

    public boolean isSelectAll() {
        return mSelectAll;
    }

    public void setItemChecked(int position, boolean value) {
        mListView.setItemChecked(position, value);
        notifyItemChecked();
    }

    public int getCount() {
        int nRet = 0;
        if (mListView != null) {
            nRet = mListView.getCount();
        }
        return nRet;
    }

    public ArrayList<FileRecord> getSelectedFile() {
        ArrayList<FileRecord> ret;
        if (mSelectAll) {
            ret = _getUnSelectedFile();
        } else {
            ret = _getSelectedFile();
        }

        return ret;
    }

    private ArrayList<FileRecord> _getSelectedFile() {
        ArrayList<FileRecord> ret = new ArrayList<>();
        SparseBooleanArray arr = mListView.getCheckedItemPositions();

        if (arr != null) {
            FileRecord record;
            int idx;

            for (int i = 0; i < arr.size(); i++) {
                if (arr.valueAt(i)) {
                    idx = arr.keyAt(i);
                    record = getAdapter().getFileRecord(idx);
                    ret.add(record);
                }
            }
        }

        return ret;
    }

    private ArrayList<FileRecord> _getUnSelectedFile() {
        ArrayList<FileRecord> ret = new ArrayList<>();
        SparseBooleanArray arr = mListView.getCheckedItemPositions();

        if (mAllPosition == null) {
            createAllPosition();
        }

        if (arr != null) {
            for (Integer idx : mAllPosition) {
                if (!arr.get(idx)) {
                    ret.add(mAdapter.getFileRecord(idx));
                }
            }
        }
        return ret;

    }

    public ArrayList<Integer> getSelectedFilePositions() {
        ArrayList<Integer> ret;

        if (mSelectAll) {
            ret = _getUnSelectedFilePositions();
        } else {
            ret = _getSelectedFilePositions();
        }

        return ret;
    }

    private ArrayList<Integer> _getSelectedFilePositions() {
        ArrayList<Integer> ret = new ArrayList<>();
        SparseBooleanArray arr = mListView.getCheckedItemPositions();

        if (arr != null) {
            int idx;
            for (int i = 0; i < arr.size(); i++) {
                if (arr.valueAt(i)) {
                    idx = arr.keyAt(i);
                    ret.add(idx);
                }
            }
        }
        return ret;
    }

    private ArrayList<Integer> mAllPosition;

    private void createAllPosition() {
        mAllPosition = new ArrayList<>();

        int nCnt = getAdapter().getItemCount();

        for (int i = 0; i < nCnt; i++) {
            if (getAdapter().isCheckable(i)) {
                mAllPosition.add(i);
            }
        }
    }

    private ArrayList<Integer> _getUnSelectedFilePositions() {
        ArrayList<Integer> ret = new ArrayList<>();
        SparseBooleanArray arr = mListView.getCheckedItemPositions();

        if (mAllPosition == null) {
            createAllPosition();
        }

        if (arr != null) {
            for (Integer idx : mAllPosition) {
                if (!arr.get(idx)) {
                    ret.add(idx);
                }
            }
        }
        return ret;
    }

    public void setItemsChecked(ArrayList<Integer> selectPos) {
        if (selectPos != null && !selectPos.isEmpty()) {
            if (mListView != null) {
                for (Integer pos : selectPos) {
                    if (pos >= 0 && !isItemChecked(pos)) {
                        mListView.setItemChecked(pos, true);
                    }
                }
            }
            notifyItemChecked();
        }
    }

    public boolean isItemChecked(int position) {
        return mSelectAll ^ mListView.isItemChecked(position);
    }

    public FileRecord getFileRecord(int position) {
        return mAdapter.getFileRecord(position);
    }

    public void setOnItemClickListener(AdapterView.OnItemClickListener listener) {
        mListView.setOnItemClickListener(listener);
    }

    public void setOnItemLongClickListener(AdapterView.OnItemLongClickListener listener) {
        mListView.setOnItemLongClickListener(listener);
    }

    public void setChoiceMode(int choiceMode) {
        if (choiceMode == ListView.CHOICE_MODE_NONE) {
            mListView.clearChoices();

            int cnt = mListView.getChildCount();

            for (int i = 0; i < cnt; i++) {
                View view = mListView.getChildAt(i);
                if (view instanceof Checkable) {
                    ((Checkable) view).setChecked(mSelectAll);
                }
            }
        }

        boolean enableDragBlock = true;
        if (choiceMode == ListView.CHOICE_MODE_SINGLE) {
            enableDragBlock = false;

        }

        mListView.setChoiceMode(choiceMode);

        if (!AppFeatures.isSupportIntensity())
            mListView.setHapticFeedbackEnabled(true);

        if (mDecorator != null && (mViewType == ViewType.GRID || mViewType == ViewType.RECENT)) {
            if (choiceMode == ListView.CHOICE_MODE_SINGLE || choiceMode == ListView.CHOICE_MODE_MULTIPLE || choiceMode == ListView.CHOICE_MODE_MULTIPLE_MODAL) {
                mDecorator.disablePinchOperation();
            } else if (choiceMode == ListView.CHOICE_MODE_NONE) {
                if (!mDecorator.isPinchEnabled()) {
                    mDecorator.enablePinchOperation();
                }
            }
        }
    }

    public int getCheckedItemCount() {
        return mListView.getCheckedItemCount();
    }

    public void setVisibility(int visibility) {
        mListView.setVisibility(visibility);
    }

    public void setEmptyView(View emptyView) {
        if (mListView != null) {
            View prevEmptyView = mListView.getEmptyView();
            if (prevEmptyView != null) {
                if (!prevEmptyView.equals(emptyView)) {
                    prevEmptyView.setVisibility(View.GONE);
                } else {
                    prevEmptyView.setVisibility(View.VISIBLE);
                }
            }

            mListView.setEmptyView(emptyView);
        }
    }

    public View getEmptyView() {
        return mListView.getEmptyView();
    }

    public void setPosition(int position) {
        mListView.requestFocus();
        mListView.setSelection(position);
    }

    public int getPosition() {
        return mListView.getFirstVisiblePosition();
    }

    public void invalidateViews() {
        try {
            if (mListView != null) {
                mListView.invalidateViews();
            }
        } catch (StaleDataException e) {
            Log.e(this, "StaleDataException:" + e.toString());
        }
    }

    public AbsListView getListView() {
        return mListView;
    }

    public boolean isCheckMode() {
        return mAdapter.isCheckMode();
    }

    public boolean isEnabled(int position) {
        return mAdapter.isEnabled(position);
    }

    public void setCheckMode(boolean bShow, View actionbar, boolean isShare, boolean isPicker) {
        FileListAdapter adapter = getAdapter();
        if (adapter != null) {
            if (adapter.isCheckMode() != bShow) { // It only works when check mode is changed.
                if (!isPicker) {
                    ViEffectMgr.getInstance().showCheckBox(mContext, mListView, actionbar, bShow);
                }
                adapter.setCheckMode(bShow, isShare);
                if (!bShow) {
                    selectAll(false);
                }
            }
        }
    }

    public void clearPreValue() {
        if (mAllPosition != null) {
            mAllPosition.clear();
            mAllPosition = null;
        }
    }

    public void onConfigurationChanged() {
        refreshLayout();
    }

    public void stopPinchZoomWorking() {
        if (mDecorator != null) {
            mDecorator.stopPinchZoomWorking();
        }
    }

    public void refreshLayout() {
        _refreshLayout();

        if (mDecorator != null) {
            mDecorator.refreshLayout();
        }
    }

    protected void _refreshLayout() {

    }

    private int getViewStubId() {
        int ret;
        if (mDecorator != null) {
            ret = mDecorator.getViewStubId();
        } else {
            ret = _getViewStubId();
        }
        return ret;
    }

    private int getListLayoutId() {
        int ret;
        if (mDecorator != null) {
            ret = mDecorator.getListLayoutId();
        } else {
            ret = _getListLayoutId();
        }
        return ret;
    }

    public int getItemLayoutId() {
        int ret;
        if (mDecorator != null) {
            ret = mDecorator.getItemLayoutId();
        } else {
            ret = _getItemLayoutId();
        }
        return ret;
    }

    protected int _getViewStubId() {
        return -1;
    }

    protected abstract int _getListLayoutId();

    protected abstract int _getItemLayoutId();

    public int getViewType() {
        return mViewType;
    }

    public void setFastScrollEnabled(boolean enabled) {
        //HYL
        enabled = false;
    }

    private boolean mIsFastScrolling = false;


    public boolean isFastScrolling() {
        return mIsFastScrolling;
    }

    public void twSetGoToTopEnabled(boolean enabled) {
        try {
            Class<?> twAbsListViewClass = Class.forName("android.widget.AbsListView");
            Method semEnableGoToTop = twAbsListViewClass.getMethod("semSetGoToTopEnabled", boolean.class);
            semEnableGoToTop.invoke(mListView, enabled);
        } catch (Exception e) {
            Log.e(this, "Exception:" + e.toString());
        }
    }

    public void setDeleteAnimation() {
        if (mFragment != null) {
            ViEffectMgr.getInstance().setDeleteListItem(mFragment.getProcessId(),
                    mContext, mListView, getSelectedFilePositions());
        }
    }

    public boolean doDeleteAnimation() {
        return ViEffectMgr.getInstance().doDeleteListItem(mFragment);
    }

    public void onLongPressDragStarted(int startX, int startY) {
    }

    public void onLongPressDragEnded(int endX, int endY) {
    }

    private boolean mSplitBarPressed = false;

    public boolean isSplitBarPressed() {
        return mSplitBarPressed;
    }

    public void onSplitBarPressed() {
        if (mViewType == ViewType.GRID) {
            mSplitBarPressed = true;
        }
    }

    public void onSplitBarReleased() {
        if (mSplitBarPressed) {
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    mListView.invalidateViews();
                }
            }, 100);
            mSplitBarPressed = false;
        }
    }
}
